/**
 ****************************************************************************
 * Copyright (C) Marcelo F. Ochoa. All rights reserved.                      *
 * ------------------------------------------------------------------------- *
 * This software is published under the terms of the Apache Software License *
 * version 1.1, a copy of which has been included  with this distribution in *
 * the LICENSE file.                                                         *
 */
 
package com.prism.toolkit.http;

import com.prism.toolkit.Jowa;

import com.prism.toolkit.Jxtp;


import java.io.BufferedReader;

import java.security.Principal;

import java.sql.Connection;
import java.sql.SQLException;

import java.text.DateFormat;
import java.text.SimpleDateFormat;

import java.util.Collections;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Locale;
import java.util.Map;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletInputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import oracle.jdbc.OraclePreparedStatement;
import oracle.jdbc.OracleResultSet;

import org.apache.log4j.Logger;

public class JxtpHttpServletRequest implements HttpServletRequest {
    Logger log = Logger.getLogger(JxtpHttpServletRequest.class);

    /**
     * This hashtable stores the rows of session_roles system view for
     * implementing isUserInRole() method.
     */
    Hashtable roles = null;

    /**
     * This hashtable stores OWA CGI variables passed from the server side to
     * be used as their HTTP headers values
     */
    Hashtable headers = new Hashtable();

    /**
     * This hashtable stores Request Attributes
     * @see #setAttribute
     * @see #getAttribute
     */
    Hashtable attributes = new Hashtable();
    
    JxtpHttpServletSession currentSession = null;
    
    public JxtpHttpServletRequest() {
        String headerString;
        headerString = Jowa.GETCGIVAR("AUTHORIZATION");
        if (headerString != null && headerString.length() > 0)
            headers.put("AUTHORIZATION", headerString);
        headerString = Jowa.GETCGIVAR("HTTP_REFERER");
        if (headerString != null && headerString.length() > 0)
            headers.put("Referer", headerString);
        headerString = Jowa.GETCGIVAR("HTTP_USER_AGENT");
        if (headerString != null && headerString.length() > 0)
            headers.put("User-Agent", headerString);
        headerString = Jowa.GETCGIVAR("HTTP_PRAGMA");
        if (headerString != null && headerString.length() > 0)
            headers.put("Pragma", headerString);
        headerString = Jowa.GETCGIVAR("HTTP_HOST");
        if (headerString != null && headerString.length() > 0)
            headers.put("Host", headerString);
        headerString = Jowa.GETCGIVAR("HTTP_ACCEPT");
        if (headerString != null && headerString.length() > 0)
            headers.put("Accept", headerString);
        headerString = Jowa.GETCGIVAR("HTTP_ACCEPT_ENCODING");
        if (headerString != null && headerString.length() > 0)
            headers.put("Accept-Encoding", headerString);
        headerString = Jowa.GETCGIVAR("HTTP_ACCEPT_LANGUAGE");
        if (headerString != null && headerString.length() > 0)
            headers.put("Accept-Language", headerString);
        headerString = Jowa.GETCGIVAR("HTTP_ACCEPT_CHARSET");
        if (headerString != null && headerString.length() > 0)
            headers.put("Accept-Charset", headerString);
        headerString = Jowa.GETCGIVAR("HTTP_IF_MODIFIED_SINCE");
        if (headerString != null && headerString.length() > 0)
            headers.put("If-Modified-Since", headerString);
        headerString = Jowa.GETCGIVAR("HTTP_COOKIE");
        if (headerString != null && headerString.length() > 0)
            headers.put("Cookie", headerString);
        log.debug(".JxtpHttpServletRequest() called.");
    }

    /**
   * @return
   */
    public String getAuthType() {
        return Jowa.GETCGIVAR("AUTH_TYPE");
    }

    /**
   * @return
   */
    public Cookie[] getCookies() {
        return new Cookie[0];
    }

    /**
   * @param string
   * @return
   */
    public long getDateHeader(String string) {
        if ("If-Modified-Since".equals(string)) {
            String argValue = Jowa.GETCGIVAR("HTTP_IF_MODIFIED_SINCE");
            DateFormat df =
                new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'",
                                                 java.util.Locale.US);
            try {
                java.util.Date lastClientMod = df.parse(argValue);
                if (log.isDebugEnabled())
                    log
                    .debug("If-Modified-Since:" + lastClientMod.getTime() / 1000 *
                              1000);
                return lastClientMod.getTime();
            } catch (Exception e) {
                log
                .warn(".CgiVars - Error parsing If-Modified-Since header", e);
                return 0L;
            }
        } else
            return 0L;
    }

    /**
   * @param string
   * @return
   */
    public String getHeader(String string) {
        return (String)headers.get(string);
    }

    /**
   * @param string
   * @return
   */
    public Enumeration getHeaders(String string) {
        return headers.elements();
    }

    /**
   * @return
   */
    public Enumeration getHeaderNames() {
        return headers.keys();
    }

    /**
   * @param string
   * @return
   */
    public int getIntHeader(String string) {
        return 0;
    }

    /**
   * @return
   */
    public String getMethod() {
        return Jowa.GETCGIVAR("REQUEST_METHOD");
    }

    /**
   * @return
   */
    public String getPathInfo() {
        return Jowa.GETCGIVAR("PATH_INFO");
    }

    /**
   * @return
   */
    public String getPathTranslated() {
        return Jowa.GETCGIVAR("PATH_TRANSLATED");
    }

    public String getContextPath() {
        return Jowa.GETCGIVAR("SCRIPT_NAME");
    }

    public String getQueryString() {
        return Jowa.GETCGIVAR("QUERY_STRING");
    }

    public String getRemoteUser() {
        return Jowa.GETCGIVAR("REMOTE_USER");
    }

    public boolean isUserInRole(String string) {
        if (roles==null) { // load session_roles values
          roles = new Hashtable();
          OraclePreparedStatement stmt = null;
          OracleResultSet rset = null;
          try {
            Connection conn = JxtpHttpServletSession.getConnection();
            stmt = (OraclePreparedStatement)conn.prepareStatement(
                "select * from session_roles");
            rset = (OracleResultSet)stmt.executeQuery();
            while(rset.next()) {
              String rol = rset.getString(1);
              roles.put(rol,"");
            }
            rset.close();
            rset = null;
            stmt.close();
            stmt = null;
          } catch (SQLException s) {
            log.warn(".isUserInRole(String) - Error loading session_roles",s);  
          } finally {
              if (rset!=null) 
                try {
                  rset.close();
                  rset = null;
                } catch (SQLException s) {
                  log.warn(".isUserInRole(String) - Error closing resultSet",s);  
                }
              if (stmt!=null) 
                try {
                  stmt.close();
                  stmt = null;
                } catch (SQLException s) {
                  log.warn(".isUserInRole(String) - Error closing statement",s);  
                }
          }
        }
        return roles.containsKey(string.toUpperCase());
    }

    public Principal getUserPrincipal() {
        return null;
    }

    public String getRequestedSessionId() {
        String id = Jxtp.getCookie("JSERVER_SESSION");
        if (log.isDebugEnabled())
          log.debug(".getRequestedSessionId called with JSERVER_SESSION="+id);
        if (id==null) { // Sanity checks
          currentSession = null;
          return null;
        }
        if (currentSession!=null && id.equals(currentSession.getId())) {
            // there is a valid ID either in the cookie and in the currentSession
            log.debug(".getRequestedSessionId - currentSession is equal to JSERVER_SESSION id");
            return id;
        } else {
            // There is a cookie ID, try to instantiate a Session from the store
            currentSession = new JxtpHttpServletSession(id);
            return ((currentSession!=null) ? currentSession.getId() : null);
        }
    }

    public String getRequestURI() {
        return null;
    }

    public StringBuffer getRequestURL() {
        return null;
    }

    public String getServletPath() {
        return Jowa.GETCGIVAR("SCRIPT_PREFIX");
    }

    /**
     * Returns the current HttpSession associated with this request or,
     * if there is no current session and b is true, returns a new session.
     * @param b
     * @return HttpSession
     */
    public HttpSession getSession(boolean b) {
        String id = Jxtp.getCookie("JSERVER_SESSION");
        if (log.isDebugEnabled())
          log.debug(".getSession("+b+") called with JSERVER_SESSION="+id);
        if (id==null) { // there is no valid cookie
            if (b) // create a new Session
              currentSession = new JxtpHttpServletSession();
            else // return null, due to user want to not create a new session
              currentSession = null;  
        } else // there is a session cookie
          try {
              if (currentSession!=null && id.equals(currentSession.getId()))
                return currentSession; // the cookie id is equal to the pre-cached session
              else // try to instantiate the cookie value with an stored session
                currentSession = new JxtpHttpServletSession(id);
          } catch (InstantiationError i) {
              if (b) // create a new Session
                currentSession = new JxtpHttpServletSession();
              else // return null, due to user don't want to create a new session
                currentSession = null;  
          }
        return currentSession;
    }

    /**
     * Returns the current session associated with this request,
     * or if the request does not have a session, creates one.
     * @return HttpSession
     */
    public HttpSession getSession() {
        return getSession(true);
    }

    public boolean isRequestedSessionIdValid() {
        String id = Jxtp.getCookie("JSERVER_SESSION");
        if (log.isDebugEnabled())
          log.debug(".isRequestedSessionIdValid called with JSERVER_SESSION="+id);
        if (id==null) { // there is no valid cookie
              return false;  
        } else // there is a session cookie
          try {
              if (currentSession==null) // there is no pre-cached session
                // try to instantiate the cookie value with an stored session
                currentSession = new JxtpHttpServletSession(id);
          } catch (InstantiationError i) {
              return false;  
          }
        // the cookie id is equal to the pre-cached session
        return id.equals(currentSession.getId());
    }

    public boolean isRequestedSessionIdFromCookie() {
        return true;
    }

    public boolean isRequestedSessionIdFromURL() {
        return false;
    }

    public boolean isRequestedSessionIdFromUrl() {
        return false;
    }

    public Object getAttribute(String string) {
        return this.attributes.get(string);
    }

    public Enumeration getAttributeNames() {
        return this.attributes.keys();
    }

    public String getCharacterEncoding() {
        return Jowa.GETCGIVAR("REQUEST_CHARSET");
    }

    public void setCharacterEncoding(String string) {
    }

    public int getContentLength() {
        return Integer.parseInt(Jowa.GETCGIVAR("CONTENT_LENGTH"));
    }

    public String getContentType() {
        return Jowa.GETCGIVAR("CONTENT_TYPE");
    }

    public ServletInputStream getInputStream() {
        return null;
    }

    public String getParameter(String string) {
        return null;
    }


    public Enumeration getParameterNames() {
        return null;
    }

    public String[] getParameterValues(String string) {
        return new String[0];
    }

    public Map getParameterMap() {
        return Collections.EMPTY_MAP;
    }

    public String getProtocol() {
        return Jowa.GETCGIVAR("SERVER_PROTOCOL");
    }

    public String getScheme() {
        return Jowa.GETCGIVAR("REQUEST_PROTOCOL");
    }

    public String getServerName() {
        return Jowa.GETCGIVAR("SERVER_NAME");
    }

    public int getServerPort() {
        return Integer.parseInt(Jowa.GETCGIVAR("SERVER_PORT"));
    }

    public BufferedReader getReader() {
        return null;
    }

    public String getRemoteAddr() {
        return Jowa.GETCGIVAR("REMOTE_ADDR");
    }

    public String getRemoteHost() {
        return Jowa.GETCGIVAR("REMOTE_HOST");
    }

    public void setAttribute(String string, Object object) {
       this.attributes.put(string,object);
    }

    public void removeAttribute(String string) {
       this.attributes.remove(string);
    }

    public Locale getLocale() {
        return null;
    }

    public Enumeration getLocales() {
        return null;
    }

    public boolean isSecure() {
        return false;
    }

    public RequestDispatcher getRequestDispatcher(String string) {
        return null;
    }

    public String getRealPath(String string) {
        return null;
    }

    public int getRemotePort() {
        return Integer.parseInt(Jowa.GETCGIVAR("REMOTE_PORT"));
    }

    public String getLocalName() {
        return null;
    }

    public String getLocalAddr() {
        return null;
    }

    public int getLocalPort() {
        return 0;
    }
}
